﻿/*
 * MediaDevice.cpp
 *
 *  Created on: 2017年5月26日
 *      Author: chuanjiang.zh
 */

#include "MediaDevice.h"

extern "C"
{
	#include <libavutil/time.h>
}

MediaDevice::MediaDevice():
	m_streamCallback(),
	m_streamUser(),
	m_channel()
{
}

MediaDevice::~MediaDevice()
{
	close();
}

bool MediaDevice::open(int chl, const std::string& url)
{
	m_channel = chl;
	m_url = url;

	int rc = m_reader.open(m_url.c_str());

	return (rc == 0);
}

void MediaDevice::close()
{
	stopStream();
}

bool MediaDevice::isOpen()
{
	return isRunning();
}

int MediaDevice::startStream(MFormat* fmt)
{
	if (!m_reader.isOpen())
	{
		int rc = m_reader.open(m_url.c_str());
		if (rc != 0)
		{
			return EINVAL;
		}
	}

	start();

	return 0;
}

int MediaDevice::stopStream()
{
	if (isRunning())
	{
		stop();
	}

	m_reader.close();

	return 0;
}

int MediaDevice::getStreamFormat(MFormat* fmt)
{
	fmt->width = m_reader.m_width;
	fmt->height = m_reader.m_height;
	fmt->framerate = m_reader.m_fps;
	fmt->codec = m_reader.m_codec;
	fmt->vProp = (uint8_t*)(m_reader.m_prop.c_str());
	fmt->vPropSize = m_reader.m_prop.size();
	fmt->clockRate = AV_TIME_BASE;

	fmt->channels = m_reader.m_channels;
	fmt->sampleRate = m_reader.m_sampleRate;
	fmt->audioCodec = m_reader.m_acodec;
	fmt->config = (uint8_t*)(m_reader.m_config.c_str());
	fmt->configSize = m_reader.m_config.size();
	fmt->audioRate = AV_TIME_BASE;

	return 0;
}

int MediaDevice::setStreamCallback(MediaStreamCallback cb, void* user)
{
	m_streamCallback = cb;
	m_streamUser = user;

	return 0;
}

int MediaDevice::run()
{
	while (!m_canExit)
	{
		AVPacket pkt;
		av_init_packet(&pkt);

		int rc = m_reader.read(pkt);
		if (rc != 0)
		{
			break;
		}

		firePacket(pkt);

		av::TimePoint tp(av_gettime(), pkt.dts);

		if (!m_timePoint.isSet())
		{
			m_timePoint = tp;
		}

		if (!m_reader.isLive())
		{
			int64_t elapse = tp.getOffset(m_timePoint);
			if (elapse > 0 && elapse < AV_TIME_BASE)
			{
				av_usleep(elapse);
			}
		}

		av_packet_unref(&pkt);
	}
	return 0;
}

void MediaDevice::firePacket(AVPacket& pkt)
{
	MPacket packet;
	memset(&packet, 0, sizeof(packet));

	packet.data = pkt.data;
	packet.size = pkt.size;
	packet.duration = pkt.duration;
	packet.flags = pkt.flags;
	packet.pts = pkt.pts;
	packet.type = m_reader.isVideo(pkt) ? MTYPE_VIDEO : MTYPE_AUDIO;

	if (m_streamCallback)
	{
		(*m_streamCallback)(&packet, m_streamUser, m_channel);
	}

}
